home *** CD-ROM | disk | FTP | other *** search
- char *versio = "C-Kermit 5A(189)-XPR, 14 Feb 94"; /* Version herald. */
- long vernum = 501189L;
- /*
- String and numeric version numbers, keep these two in sync!
- First digit of vermum = major version, i.e. 5.
- Second 2 digits of vernum: 00 = no minor version, 01 = A, 02 = B, etc.
- Last three digits are edit number.
- For Macintosh, also remember to change the Mac-specific version in ckmkr2.r.
- */
-
- #ifndef VERWHO
- /* Change verwho in following line, or with -DVERWHO=x in makefile CFLAGS. */
- #define VERWHO 91330
- #endif /* VERWHO */
- int verwho = VERWHO; /* Who produced this version, 0 = Columbia University */
- /*
- IMPORTANT: If you are working on your own private version of C-Kermit, please
- include some special notation, like your site name or your initials, in the
- "versio" string, e.g. "5A(182)-XXX", and use a nonzero code for the "verwho"
- variable (e.g. in the USA use your zip code). Unless we stick to this
- discipline, divergent copies of C-Kermit will begin to appear that are
- intistinguishable from each other, which is a big support issue. Also, if
- you have edited C-Kermit and made copies available to others, please add
- appropriate text to the BUG command (ckuus6.c, function dobug()).
- */
- #define CKXMAI
-
- /* C K X M A I -- Amiga XPR C-Kermit "Main" program */
-
- /*
- Author: Stephen R. Walton (swalton@huey.csun.edu)
- California State University, Northridgen
- First released March 1993.
- Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
- York. Permission is granted to any individual or institution to use this
- software as long as it is not sold for profit. This copyright notice must be
- retained. This software may not be included in commercial products without
- written permission of Columbia University.
- */
- /*
- The Kermit file transfer protocol was developed at the Columbia University
- Center for Computing Activities (CUCCA). It is named after Kermit the Frog,
- star of the television series THE MUPPET SHOW; the name is used by permission
- of Henson Associates, Inc. "Kermit" is also Celtic for "free".
- */
- /*
- DISCLAIMER:
-
- The C-Kermit software is provided in source code form by Kermit Development
- and Distribution, Columbia University. The software is provided "as is;" no
- other warranty is provided, express or implied, including without
- limitations, any implied warranty of merchantability or implied warranty of
- fitness for a particular purpose.
-
- Neither Columbia University nor any of the contributors to the C-Kermit
- development effort, including, but not limited to, AT&T, Digital Equipment
- Corporation, Data General Corporation, or International Business Machines
- Corporation, warrant C-Kermit software or documentation in any way. In
- addition, neither the authors of any Kermit programs, publications or
- documentation, nor Columbia University nor any contributing institutions or
- individuals acknowledge any liability resulting from program or
- documentation errors.
- */
-
- /*
- ckcsym.h is used for for defining symbols that normally would be defined
- using -D or -d on the cc command line, for use with compilers that don't
- support this feature.
- */
- #include "ckcsym.h"
- #include "ckcasc.h" /* ASCII character symbols */
- #include "ckcdeb.h" /* Debug & other symbols */
- #include "ckcker.h" /* Kermit symbols */
- #include "ckcnet.h" /* Network symbols */
-
- char *srvtxt = "Now in server mode. But shouldn't be\r\n";
-
- /* Declarations for Send-Init Parameters */
-
- int spsiz = DSPSIZ, /* Current packet size to send */
- spmax = DSPSIZ, /* Biggest packet size we can send */
- spsizr = DSPSIZ, /* Send-packet size requested */
- spsizf = 0, /* Flag to override size negotiation */
- rpsiz = DRPSIZ, /* Biggest we want to receive */
- urpsiz = DRPSIZ, /* User-requested receive pkt size */
- maxrps = MAXRP, /* Maximum incoming long packet size */
- maxsps = MAXSP, /* Maximum outbound l.p. size */
- maxtry = MAXTRY, /* Maximum retries per packet */
- wslots = 1, /* Window size currently in use */
- wslotr = 1, /* Window size from SET WINDOW */
- wslotn = 1, /* Window size negotiated in S-pkt */
- timeouts = 0, /* For statistics reporting */
- spackets = 0, /* ... */
- rpackets = 0, /* ... */
- retrans = 0, /* ... */
- crunched = 0, /* ... */
- wmax = 0, /* ... */
- wcur = 0, /* ... */
- srvdis = 0, /* Server file xfer display */
- srvtim = DSRVTIM, /* Server command wait timeout */
- /*
- timint is the timeout interval I use when waiting for a packet.
- pkttim is the SET RECEIVE TIMEOUT value, sent to the other Kermit.
- rtimo is the SET SEND TIMEOUT value. rtimo is the initial value of
- timint. timint is changed by the value in the incoming negotiation
- packet unless a SET SEND TIMEOUT command was given.
- */
- timint = DMYTIM, /* Timeout interval I use */
- pkttim = URTIME, /* Timeout I want you to use */
- rtimo = DMYTIM, /* Normal packet wait timeout */
- timef = 0, /* Flag to override what you ask */
- npad = MYPADN, /* How much padding to send */
- mypadn = MYPADN, /* How much padding to ask for */
- bctr = 1, /* Block check type requested */
- bctu = 1, /* Block check type used */
- bctl = 1, /* Block check length */
- ebq = MYEBQ, /* 8th bit prefix */
- ebqflg = 0, /* 8th-bit quoting flag */
- rqf = -1, /* Flag used in 8bq negotiation */
- rq = 0, /* Received 8bq bid */
- sq = 'Y', /* Sent 8bq bid */
- rpt = 0, /* Repeat count */
- rptq = MYRPTQ, /* Repeat prefix */
- rptflg = 0, /* Repeat processing flag */
- rptena = 1, /* Repeat processing enabled */
- xfrcan = 1, /* Transfer cancellation enabled */
- xfrchr = 3, /* Transfer cancel char = Ctrl-C */
- xfrnum = 2; /* Need two of them. */
-
- int capas = 9, /* Position of Capabilities */
- atcapb = 8, /* Attribute capability */
- atcapr = 1, /* requested */
- atcapu = 0, /* used */
- swcapb = 4, /* Sliding Window capability */
- swcapr = 1, /* requested (allowed) */
- swcapu = 0, /* used */
- lpcapb = 2, /* Long Packet capability */
- lpcapr = 1, /* requested */
- lpcapu = 0, /* used */
- lscapb = 32, /* Locking Shift capability */
- lscapr = 1, /* requested by default */
- lscapu = 0; /* used */
-
- /* Flags for whether to use particular attributes */
-
- int atenci = 1, /* Encoding in */
- atenco = 1, /* Encoding out */
- atdati = 1, /* Date in */
- atdato = 1, /* Date out */
- atdisi = 1, /* Disposition in/out */
- atdiso = 1,
- atleni = 1, /* Length in/out (both kinds) */
- atleno = 1,
- atblki = 1, /* Blocksize in/out */
- atblko = 1,
- attypi = 1, /* File type in/out */
- attypo = 1,
- atsidi = 1, /* System ID in/out */
- atsido = 1,
- atsysi = 1, /* System-dependent parameters in/out */
- atsyso = 1;
-
- CHAR padch = MYPADC, /* Padding character to send */
- mypadc = MYPADC, /* Padding character to ask for */
- seol = MYEOL, /* End-Of-Line character to send */
- eol = MYEOL, /* End-Of-Line character to look for */
- ctlq = CTLQ, /* Control prefix in incoming data */
- myctlq = CTLQ, /* Outbound control character prefix */
- myrptq = MYRPTQ; /* Repeat prefix I want to use */
-
- struct zattr iattr; /* Incoming file attributes */
-
- /* File related variables, mainly for the benefit of VAX/VMS */
-
- int fblksiz = DBLKSIZ; /* File blocksize */
- int frecl = DLRECL; /* File record length */
- int frecfm = XYFF_S; /* File record format (default = stream) */
- int forg = XYFO_S; /* File organization (sequential) */
- int fcctrl = XYFP_N; /* File carriage control (ctrl chars) */
-
- int lf_opts = 0;
-
- /* Packet-related variables */
-
- int pktnum = 0, /* Current packet number */
- sndtyp = 0, /* Type of packet just sent */
- rcvtyp = 0, /* Type of packet just received */
- rsn, /* Received packet sequence number */
- rln, /* Received packet length */
- size, /* Current size of output pkt data */
- osize, /* Previous output packet data size */
- maxsize, /* Max size for building data field */
- spktl = 0, /* Length packet being sent */
- rpktl = 0, /* Length of packet just received */
- rprintf, /* REMOTE PRINT flag */
- rmailf; /* MAIL flag */
-
- CHAR
- #ifdef NO_MORE /* Buffers used before sliding windows... */
- sndpkt[MAXSP+100], /* Entire packet being sent */
- recpkt[MAXRP+200], /* Packet most recently received */
- data[MAXSP+4], /* Packet data buffer */
- #endif
- #ifdef DYNAMIC
- *srvcmd = (CHAR *)0, /* Where to decode server command */
- #else
- srvcmd[MAXRP+4], /* Where to decode server command */
- #endif
- padbuf[95], /* Buffer for send-padding */
- *recpkt,
- *rdatap, /* Pointer to received packet data */
- *data = (CHAR *)0, /* Pointer to send-packet data */
- *srvptr, /* Pointer to srvcmd */
- mystch = SOH, /* Outbound packet-start character */
- stchr = SOH; /* Incoming packet-start character */
-
- /* File-related variables */
-
- char filnam[257]; /* Name of current file. */
- char cmdfil[80]; /* Application file name. */
-
- int nfils = 0; /* Number of files in file group */
- long fsize; /* Size of current file */
- int wildxpand = 0; /* Who expands wildcards */
- int clfils = 0; /* Flag for command-line files */
- int stayflg = 0; /* Flag for "stay", i.e. "-S" */
-
- /* Communication line variables */
-
- char ttname[80]; /* Name of communication line. */
-
- #ifdef MAC
- int connected = 0; /* true if connected */
- int startconnected; /* initial state of connected */
- #endif /* MAC */
-
- long speed = -1L; /* Line speed */
-
- int parity, /* Parity specified, 0,'e','o',etc */
- autopar = 0, /* Automatic parity change flag */
- sosi = 0, /* Shift-In/Out flag */
- flow, /* Flow control */
- turn = 0, /* Line turnaround handshake flag */
- turnch = XON, /* Line turnaround character */
- duplex = 0, /* Duplex, full by default */
- escape = DFESC, /* Escape character for connect */
- delay = DDELAY, /* Initial delay before sending */
- tnlm = 0, /* Terminal newline mode */
- mdmtyp = 0; /* Modem type (initially none) */
-
- int network = 0;
-
- /* Other recent additions */
-
- int tlevel = -1; /* Take-file command level */
- #ifndef NOSPL
- extern int cmdlvl; /* Command level */
- extern int maclvl; /* Macro invocation level */
- #endif /* NOSPL */
- int carrier = CAR_AUT; /* Pay attention to carrier signal */
- int cdtimo = 0; /* Carrier wait timeout */
- int xitsta = GOOD_EXIT; /* Program exit status */
- int fncact = XYFX_X; /* REPLACE for XPR Kermit */
- int bgset = -1; /* BACKGROUND mode set explicitly */
- #ifdef UNIX
- int suspend = DFSUSP; /* Whether SUSPEND command, etc, */
- #else /* is to be allowed. */
- int suspend = 0;
- #endif /* UNIX */
-
- /* Statistics variables */
-
- long filcnt, /* Number of files in transaction */
- flci, /* Characters from line, current file */
- flco, /* Chars to line, current file */
- tlci, /* Chars from line in transaction */
- tlco, /* Chars to line in transaction */
- ffc, /* Chars to/from current file */
- tfc, /* Chars to/from files in transaction */
- rptn; /* Repeated characters compressed */
-
- int tsecs = 0; /* Seconds for transaction */
- int fsecs = 0; /* Per-file timer */
-
- /* Flags */
-
- int deblog = 0, /* Flag for debug logging */
- debses = 0, /* Flag for DEBUG SESSION */
- pktlog = 0, /* Flag for packet logging */
- seslog = 0, /* Session logging */
- tralog = 0, /* Transaction logging */
- displa = 1, /* File transfer display on/off */
- stdouf = 0, /* Flag for output to stdout */
- stdinf = 0, /* Flag for input from stdin */
- xflg = 0, /* Flag for X instead of F packet */
- hcflg = 0, /* Doing Host command */
- fncnv = 1, /* Flag for file name conversion */
- binary = 0, /* Flag for binary file */
- savmod = 0, /* Saved file mode (whole session) */
- bsave = 0, /* Saved file mode (per file) */
- bsavef = 0, /* Flag if bsave was used. */
- cmask = 0177, /* Connect byte mask */
- fmask = 0377, /* File byte mask */
- warn = 0, /* Flag for file warning */
- quiet = 0, /* Be quiet during file transfer */
- local = 1, /* Flag for external tty vs stdout */
- server = 0, /* Flag for being a server */
- cflg = 0, /* Connect before transaction */
- cnflg = 0, /* Connect after transaction */
- cxseen = 0, /* Flag for cancelling a file */
- czseen = 0, /* Flag for cancelling file group */
- discard = 0, /* Flag for file to be discarded */
- keep = 0, /* Keep incomplete files */
- unkcs = 1, /* Keep file w/unknown character set */
- nakstate = 0, /* In a state where we can send NAKs */
- dblchar = -1; /* Character to double when sending */
-
- /* Variables passed from command parser to protocol module */
-
- #ifndef NOSPL
- _PROTOTYP( int parser, (int) ); /* The parser itself */
- char *clcmds = NULL; /* Pointer to command-line commands */
- #endif /* NOSPL */
-
- CHAR sstate = (CHAR) 0; /* Starting state for automaton */
- CHAR zstate = (CHAR) 0; /* For remembering sstate */
- char *cmarg = ""; /* Pointer to command data */
- char *cmarg2 = ""; /* Pointer to 2nd command data */
- char **cmlist; /* Pointer to file list in argv */
-
- /* Flags for the ENABLE and DISABLE commands */
-
- int en_cwd = 1; /* CD/CWD */
- int en_del = 1; /* DELETE */
- int en_dir = 1; /* DIRECTORY */
- int en_fin = 1; /* FINISH/BYE */
- int en_get = 1; /* GET */
- #ifndef NOPUSH
- int en_hos = 1; /* HOST enabled */
- #else
- int en_hos = 0; /* HOST disabled */
- #endif /* NOPUSH */
- int en_sen = 1; /* SEND */
- int en_set = 1; /* SET */
- int en_spa = 1; /* SPACE */
- int en_typ = 1; /* TYPE */
- int en_who = 1; /* WHO */
- #ifdef datageneral
- /* Data General AOS/VS can't do this */
- int en_bye = 0; /* BYE */
- #else
- int en_bye = 1; /* BYE */
- #endif /* datageneral */
-
- /* Miscellaneous */
-
- char **xargv; /* Global copies of argv */
- int xargc; /* and argc */
- int xargs; /* an immutable copy of argc */
- char *xarg0; /* and of argv[0] */
-
- extern char *dftty; /* Default tty name from ck?tio.c */
- extern int dfloc; /* Default location: remote/local */
- extern int dfprty; /* Default parity */
- extern int dfflow; /* Default flow control */
-
- /*
- Buffered file input and output buffers. See getpkt() in ckcfns.c
- and zoutdump() in the system-dependent file i/o module (usually ck?fio.c).
- */
- #ifndef DYNAMIC
- /* Now we allocate them dynamically, see getiobs() below. */
- char zinbuffer[INBUFSIZE], zoutbuffer[OBUFSIZE];
- #endif
- char *zinptr, *zoutptr;
- int zincnt, zoutcnt;
-
- _PROTOTYP( int getiobs, (void) );
-
- /*
- * xproto.h is the include file given in Appendix B. It is included
- * in ckxker.h
- */
-
- #include "ckxker.h"
-
- long (*xupdate) (), (*xswrite) (), (*xfopen) (), (*xfclose) (), (*xfread) (),
- (*xsread) (), (*xchkabort) (), (*xfnext) (), (*xffirst) (), (*xsflush) (),
- (*xfwrite) (), (*xgets) (), (*xfinfo) (), (*xunlink)() ,
- (*xsquery) (), (*xchkmisc) (), (*xsetserial)();
-
- extern CHAR start; /* The start state for the protocol. */
-
- /*
- * Local prototypes.
- */
- static KermitCd(struct XPR_IO *IO, char *dir);
- static KermitFinish(struct XPR_IO *IO);
- static KermitBye(struct XPR_IO *IO);
- static DoGeneric(struct XPR_IO *IO, char *s);
- static int setup(struct XPR_IO *IO);
-
- extern int success;
-
- /**
- *
- * Send a (list of) files
- *
- **/
- long
- XProtocolSend(IO)
- struct XPR_IO *IO;
- {
- struct XPR_UPDATE xpru;
-
- if (setup(IO) == 0)
- return 0L; /* Initialize parameters. */
-
- /*
- * Set global text/binary flag based on return value from xpr_finfo,
- * if present. We could set this on a per-file basis.
- */
- if (xfinfo)
- binary = (callad(xfinfo, IO->xpr_filename, 2L) == 1 ? 1 : 0);
- /*
- * Expand filenames. This is not exactly how I'd intended this code
- * to work. CKCPLM.DOC implies that the system-independent code
- * calls zxpand() if nfils is -1 to expand the file name list,
- * followed by calling znext() to get the list one name at a time.
- * This is not the case: zxpand() is called by the system-dependent
- * code in ckucmd.c. Following its lead, we call zxpand() here but
- * still set nfils to -1 in order to force gnfile() in the system
- * independent code to call znext().
- */
- if (zxpand(IO->xpr_filename) < 0)
- return 0L;
- nfils = -1;
- sstate = 's';
- proto();
-
- if (!success)
- return (0L);
- else
- return (1L);
- }
-
- static int getfile = 0; /* Flag as to whether to RECEIVE or GET */
-
- /**
- *
- * Receive a file.
- *
- **/
- long
- XProtocolReceive(IO)
- struct XPR_IO *IO;
- {
- struct XPR_UPDATE xpru;
- long status;
-
- if (setup(IO) == 0)
- return 0L; /* Initialize parameters. */
-
- /*
- * Read the text/binary set using xpr_finfo if present. Else use the
- * value chosen in XPRotocolSetup.
- */
- if (xfinfo) {
- /*
- * Use feature th at calling xpr_finfo with a zero-length filename
- * returns setting of internal comm program Text/Binary flag.
- */
- binary = (callad(xfinfo, "", 2L) == 1 ? 1 : 0);
- }
-
- if (getfile) {
- /*
- * Get filename, and put pointer in external Kermit variable.
- */
- cmarg2 = NULL;
- nfils = -1;
- sstate = 'r';
- #ifdef COMMENT
- if (IO->xpr_filename != NULL && IO->xpr_filename[0] != '\0')
- cmarg = IO->xpr_filename;
- else {
- status = callaa(xgets, "Host Filename", cmarg);
- if (!status)
- return (0L);
- }
- #else
- status = callaa(xgets, "Host Filename", cmarg);
- if (!status)
- return (0L);
- #endif
- } else {
- sstate = 'v';
- cmarg = cmarg2 = NULL;
- }
- proto();
-
- if (!success)
- return (0L);
- else
- return (1L);
- }
-
- /*
- * Perform a generic Kermit server command.
- */
- static
- DoGeneric(IO, s)
- struct XPR_IO *IO;
- char *s;
- {
- if (setup(IO) == 0)
- return 0; /* Set up transfer characteristics. */
- sstate = 'g';
- cmarg = s;
- proto();
- if (!success)
- return (0);
- else
- return (1);
- }
-
- /*
- * Execute a Kermit FINISH command.
- */
- static
- KermitFinish(IO)
- struct XPR_IO *IO;
- {
- return (DoGeneric(IO, "F"));
- }
-
- /*
- * Execute a Kermit BYE command.
- */
- static
- KermitBye(IO)
- struct XPR_IO *IO;
- {
- return (DoGeneric(IO, "L"));
- }
-
- /*
- * Change directory on remote server. We need to return an error if the CD
- * fails on the remote end.
- */
- static
- KermitCd(IO, dir)
- struct XPR_IO *IO;
- char *dir;
- {
- char CdCommand[100];
- int retval;
-
- CdCommand[0] = 'C';
- CdCommand[1] = (char) tochar(strlen(dir));
- strcpy(CdCommand + 2, dir);
- retval = DoGeneric(IO, CdCommand);
- return retval;
- }
-
- /**
- *
- * Setup
- *
- * First, a general-purpose comparison for either of the two possible returns
- * indicating a Yes push on a Boolean gadget.
- **/
-
- #define XprBoolTrue(s) ((stricmp(s, "yes") == 0) || (stricmp(s, "on") == 0))
-
- /*
- * Then, a small set of code to initialize a string based on a value.
- */
-
- #define XprSet(value, string) ((value) ? \
- (void) strcpy(string, YesString) : \
- (void) strcpy(string, NoString)) \
-
- static char YesString[] = "yes";
- static char NoString[] = "no";
-
- /*
- * If Setup() succeeds, flag same. Also, we don't need a file requester
- * on receive.
- */
- #define SUCCESS (XPRS_SUCCESS | XPRS_NORECREQ)
-
- extern char _H1_org, _H1_end, _H2_org, _H2_end; /* Data segment pointers */
- static void NewDataSeg(void *);
-
- #pragma regcall(NewDataSeg(a0))
-
- #include <exec/memory.h>
- #include <clib/exec_protos.h>
- #include <pragmas/exec_pragmas.h>
-
- /*
- * IMPLEMENTATION NOTE
- *
- * InitData() and NewDataSeg() implement the Manx-dependent code to
- * make XPR Kermit re-entrant. I take advantage of the fact that the
- * XPR library has only four entry points, and call the setup() routine
- * from each one. setup() in turn calls InitData(), whose job it is
- * to allocate a new data segment if IO->xpr_data is NULL, and then to
- * put that data segment address into register a4. This works for two
- * reasons: first, because the code is re-entrant up to the time the
- * call to NewDataSeg() occurs, and second, because the call to geta4())
- * which the Manx compiler inserts into the external entry points happens
- * before the call to setup() at the beginning of each routine above.
- *
- * The arguably best solution is to have a technique for returning a
- * different Library base pointer to each opener and initialize the
- * data segment then. The SAS/C compiler makes this possible.
- */
- int
- InitData(struct XPR_IO *IO) {
-
- /*
- * Allocate memory for file name buffer and options if first call. Also
- * allocate user's data segment and point us at it.
- */
- if (IO->xpr_data == NULL) {
- if ((IO->xpr_data = AllocMem(&_H2_end - &_H1_org + 4, 0L)) == NULL) {
- return 0;
- }
- CopyMem(&_H1_org, IO->xpr_data, &_H2_end - &_H1_org + 4);
- }
- NewDataSeg(IO->xpr_data);
- return(1);
- }
-
- long
- XProtocolSetup(IO)
- struct XPR_IO *IO;
- {
- long (*xoptions) ();
- #define NOPTS 15
- /*
- * The "static" here is to prevent these from being allocated off
- * the stack---we want to minimize stack usage in a library.
- */
- static struct xpr_option opt[NOPTS], *popt[NOPTS];
- #define MAXSTRING 6
- char ValueStrings[NOPTS][MAXSTRING];
- long status;
- int i, j;
- char buf[256];
-
- if (InitData(IO) == 0)
- return (XPRS_FAILURE);
-
- if ((xupdate = IO->xpr_update) == NULL)
- return (XPRS_FAILURE);
- if ((xgets = IO->xpr_gets) == NULL)
- return (XPRS_FAILURE);
-
- /*
- * In order to use xpr_options, we must have all of the three conditions
- * which follow true. Otherwise, either IO->xpr_filename is non-NULL, in
- * which case we assume it contains a setup string, or there is no
- * xpr_options, in which case we use xpr_gets to retrieve a setup string.
- */
- if (IO->xpr_filename == NULL &&
- IO->xpr_extension >= 1 &&
- (xoptions = IO->xpr_options) != NULL) {
-
- /*
- * I use a counter, i, here, so that I can stick in more options
- * without needing to change a lot of numbers. I can also skip
- * options dynamically, as in Text below.
- */
- i = 0;
- /* Announce us. */
- opt[i].xpro_description = versio;
- opt[i].xpro_type = XPRO_HEADER;
- opt[i].xpro_value = NULL;
- opt[i].xpro_length = 0;
- i++;
- /*
- * First, do the Kermit server command items.
- */
- opt[i].xpro_description = "Kermit FINISH";
- opt[i].xpro_type = XPRO_COMMAND;
- opt[i].xpro_value = NULL;
- opt[i].xpro_length = 0;
- i++;
- opt[i].xpro_description = "Kermit BYE";
- opt[i].xpro_type = XPRO_COMMAND;
- opt[i].xpro_value = NULL;
- opt[i].xpro_length = 0;
- i++;
- opt[i].xpro_description = "Kermit CD";
- opt[i].xpro_type = XPRO_COMMPAR;
- buf[0] = '\0';
- opt[i].xpro_value = buf; /* Use buf to hold dir name. */
- opt[i].xpro_length = sizeof(buf) - 1;
- i++;
- opt[i].xpro_description = "Kermit Options";
- opt[i].xpro_type = XPRO_COMMAND;
- opt[i].xpro_value = NULL;
- opt[i].xpro_length = 0;
- i++;
- /* show requester after loading pointers */
- for (j = 0; j < i; j++)
- popt[j] = &opt[j];
- status = callda(xoptions, (long) i, popt);
- /* check returned value */
- if (status == -1L)
- return XPRS_FAILURE;
- /* Check returned value to see what we are to do. */
- i = 1;
- if (status & (1L << i))
- return (KermitFinish(IO) ? SUCCESS : XPRS_FAILURE);
- i++;
- if (status & (1L << i))
- return (KermitBye(IO) ? SUCCESS : XPRS_FAILURE);
- i++;
- if (status & (1L << i))
- return (KermitCd(IO, opt[i].xpro_value) ? SUCCESS : XPRS_FAILURE);
- /* If we get to this point, we are to set options. */
- i = 0; /* Start over. */
- opt[i].xpro_description = versio;
- opt[i].xpro_type = XPRO_HEADER;
- opt[i].xpro_value = NULL;
- opt[i].xpro_length = 0;
- i++;
- /* Convert filename */
- opt[i].xpro_description = "Convert Filename";
- opt[i].xpro_type = XPRO_BOOLEAN;
- XprSet(fncnv, ValueStrings[i]);
- opt[i].xpro_value = ValueStrings[i];
- opt[i].xpro_length = MAXSTRING;
- i++;
- /* Partial file keep */
- opt[i].xpro_description = "Keep Incomplete";
- opt[i].xpro_type = XPRO_BOOLEAN;
- XprSet(keep, ValueStrings[i]);
- opt[i].xpro_value = ValueStrings[i];
- opt[i].xpro_length = MAXSTRING;
- i++;
- /* host is server */
- opt[i].xpro_description = "Host Server";
- opt[i].xpro_type = XPRO_BOOLEAN;
- XprSet(getfile, ValueStrings[i]);
- opt[i].xpro_value = ValueStrings[i];
- opt[i].xpro_length = MAXSTRING;
- i++;
- /* File name collision option */
- opt[i].xpro_description = "Collision Action";
- opt[i].xpro_type = XPRO_STRING;
- switch (fncact) {
- case XYFX_A:
- strcpy(ValueStrings[i], "A");
- break;
- case XYFX_D:
- strcpy(ValueStrings[i], "D");
- break;
- case XYFX_R:
- strcpy(ValueStrings[i], "R");
- break;
- case XYFX_X:
- strcpy(ValueStrings[i], "X");
- break;
- default:
- strcpy(ValueStrings[i], "?");
- break;
- }
- opt[i].xpro_value = ValueStrings[i];
- opt[i].xpro_length = 1;
- i++;
- /*
- * file type -- only show this if xpr_finfo not present, or returns
- * error when we try to get the file type.
- */
- if ((xfinfo = IO->xpr_finfo) == NULL ||
- (binary = (int) (callad(xfinfo, "", 2L))) == 0) {
- binary = -1; /* Flag xfinfo failed. */
- opt[i].xpro_description = "Text File";
- opt[i].xpro_type = XPRO_BOOLEAN;
- XprSet(binary ? 0 : 1, ValueStrings[i]);
- opt[i].xpro_value = ValueStrings[i];
- opt[i].xpro_length = MAXSTRING;
- i++;
- } else
- /*
- * Switch to 1 for binary, 0 for text; xpr_finfo returns 1 for
- * binary, 2 for text.
- */
- binary = (binary == 1 ? 1 : 0);
- /* Packet size */
- opt[i].xpro_description = "Packet Size";
- opt[i].xpro_type = XPRO_LONG;
- (void) sprintf(ValueStrings[i], "%-d", urpsiz);
- opt[i].xpro_value = ValueStrings[i];
- opt[i].xpro_length = MAXSTRING;
- i++;
- /* Block Check type */
- opt[i].xpro_description = "Block Check (1, 2, 3)";
- opt[i].xpro_type = XPRO_LONG;
- (void) sprintf(ValueStrings[i], "%-d", bctr);
- opt[i].xpro_value = ValueStrings[i];
- opt[i].xpro_length = MAXSTRING;
- i++;
- /* Retry Limit */
- opt[i].xpro_description = "Maximum Retries";
- opt[i].xpro_type = XPRO_LONG;
- (void) sprintf(ValueStrings[i], "%-d", maxtry);
- opt[i].xpro_value = ValueStrings[i];
- opt[i].xpro_length = MAXSTRING;
- i++;
- /* Timeout */
- opt[i].xpro_description = "Timeout (seconds)";
- opt[i].xpro_type = XPRO_LONG;
- (void) sprintf(ValueStrings[i], "%-d", rtimo);
- opt[i].xpro_value = ValueStrings[i];
- opt[i].xpro_length = MAXSTRING;
- i++;
- /* Number of windows */
- opt[i].xpro_description = "Window Slots";
- opt[i].xpro_type = XPRO_LONG;
- (void) sprintf(ValueStrings[i], "%-d", wslotr);
- opt[i].xpro_value = ValueStrings[i];
- opt[i].xpro_length = MAXSTRING;
- i++;
- /* Send packet size */
- opt[i].xpro_description = "Send Packet Size";
- opt[i].xpro_type = XPRO_LONG;
- (void) sprintf(ValueStrings[i], "%-d", (spsizf == 0 ? 0 : spsiz));
- opt[i].xpro_value = ValueStrings[i];
- opt[i].xpro_length = MAXSTRING;
- i++;
- /* Send timeout */
- opt[i].xpro_description = "Send Timeout";
- opt[i].xpro_type = XPRO_LONG;
- (void) sprintf(ValueStrings[i], "%-d", (timef == 0 ? 0 : timint));
- opt[i].xpro_value = ValueStrings[i];
- opt[i].xpro_length = MAXSTRING;
- i++;
- /* show requester after loading pointers */
- for (j = 0; j < i; j++)
- popt[j] = &opt[j];
- /* show requester */
- status = callda(xoptions, (long) i, popt);
- /* check returned value */
- if (status == -1L)
- return XPRS_FAILURE;
- i = 1; /* Skip header */
- if (status & (1L << i))
- fncnv = XprBoolTrue(opt[i].xpro_value) ? 1 : 0;
- i++;
- if (status & (1L << i))
- keep = XprBoolTrue(opt[i].xpro_value) ? 1 : 0;
- i++;
- if (status & (1L << i))
- getfile = XprBoolTrue(opt[i].xpro_value) ? 1 : 0;
- i++;
- if (status & (1L << i)) {
- switch(ValueStrings[i][0]) {
- case 'A':
- fncact = XYFX_A;
- break;
- case 'D':
- fncact = XYFX_D;
- break;
- case 'R':
- fncact = XYFX_R;
- break;
- case 'X':
- fncact = XYFX_X;
- break;
- default:
- fncact = XYFX_X; /* Default is replace */
- break;
- }
- }
- i++;
- if (xfinfo == NULL || binary == -1) {
- if (status & (1L << i))
- binary = XprBoolTrue(opt[i].xpro_value) ? 0 : 1;
- i++;
- }
- if (status & (1L << i))
- urpsiz = atoi(opt[i].xpro_value);
- i++;
- if (status & (1L << i))
- bctr = atoi(opt[i].xpro_value);
- i++;
- if (status & (1L << i))
- maxtry = atoi(opt[i].xpro_value);
- i++;
- if (status & (1L << i)) {
- rtimo = atoi(opt[i].xpro_value);
- if (rtimo < 5) rtimo = 5;
- }
- i++;
- if (status & (1L << i))
- wslotr = atoi(opt[i].xpro_value);
- i++;
- if (status & (1L << i)) {
- spsiz = atoi(opt[i].xpro_value);
- spsizf = (spsiz > 0 ? 1 : 0);
- }
- i++;
- if (status & (1L << i)) {
- timint = atoi(opt[i].xpro_value);
- timef = (timint > 0 ? 1: 0);
- }
- i++;
- } else {
- if (IO->xpr_filename != NULL)
- strcpy(buf, IO->xpr_filename); /* Save setup string */
- else { /* Prompt for command/options string */
- char collision;
-
- switch (fncact) {
- case XYFX_A:
- collision = 'A';
- break;
- case XYFX_D:
- collision = 'D';
- break;
- case XYFX_R:
- collision = 'R';
- break;
- case XYFX_X:
- collision = 'X';
- break;
- default:
- collision = '?';
- break;
- }
- sprintf(buf, "OC%c,G%c,K%c,T%c,N%c,P%d,B%d,R%d,O%d,W%d,SP%d,SO%d",
- fncnv ? 'Y' : 'N',
- getfile ? 'Y' : 'N', keep ? 'Y' : 'N',
- binary ? 'N' : 'Y',
- collision,
- urpsiz, bctr, maxtry, rtimo, wslotr,
- (spsizf <= 0 ? 0 : spsiz),
- (timef <= 0 ? 0 : timint));
- if (callaa(xgets, "Kermit Options", buf) == 0)
- return XPRS_FAILURE; /* Failed to set up? */
- }
- (void) strupr(buf);
- switch (buf[0]) {
- case 'F':
- return (KermitFinish(IO) ? SUCCESS : XPRS_FAILURE);
- case 'B':
- return (KermitBye(IO) ? SUCCESS : XPRS_FAILURE);
- case 'C':
- return (KermitCd(IO, buf + 1) ? SUCCESS : XPRS_FAILURE);
- case 'O':
- if (SetupFromString(IO, buf) == 0)
- return XPRS_FAILURE;
- break;
- case '\0':
- break;
- default:
- ioerr(IO, "Unrecognized XPR Kermit setup string");
- break;
- }
- }
- /*
- * Return success and inform caller that we don't need a requester for
- * receive.
- */
- return SUCCESS;
- }
-
- static char Delimiters[] = " \t\r\n,";
-
- int
- SetupFromString(IO, s)
- struct XPR_IO *IO;
- char *s;
- {
- char *p;
- char errbuf[50];
-
- if (*s != 'O')
- return 0; /* Options string must start with O. */
- s++; /* Skip leading O. */
- /*
- * Hunt for options with strtok. We allow whitespace and commas to
- * separate options.
- */
- for (p = strtok(s, Delimiters); p != NULL; p = strtok(NULL, Delimiters)) {
- switch (*p++) { /* Auto-increment to option */
- case 'C': /* Case conversion. */
- if (*p == 'Y' || *p == 'N')
- fncnv = (*p == 'Y');
- else
- ioerr(IO, "Illegal C option format (must be Y or N)");
- break;
- case 'G': /* Get files (Host server) */
- if (*p == 'Y' || *p == 'N')
- getfile = (*p == 'Y');
- else
- ioerr(IO, "Illegal G option format (must be Y or N)");
- break;
- case 'K': /* Keep incomplete file */
- if (*p == 'Y' || *p == 'N')
- keep = (*p == 'Y');
- else
- ioerr(IO, "Illegal K option format (must be Y or N)");
- break;
- case 'T': /* Text file */
- if (*p == 'Y' || *p == 'N')
- binary = (*p == 'N');
- else
- ioerr(IO, "Illegal T option format (must be Y or N)");
- break;
- case 'N': /* File name collision */
- switch(*p) {
- case 'A':
- fncact = XYFX_A;
- break;
- case 'D':
- fncact = XYFX_D;
- break;
- case 'R':
- fncact = XYFX_R;
- break;
- case 'X':
- fncact = XYFX_X;
- break;
- default:
- fncact = XYFX_X; /* Default is replace */
- break;
- }
- break;
- case 'P': /* Maximum packet length */
- urpsiz = atoi(p);
- break;
- case 'B': /* Block check type. */
- bctr = atoi(p);
- if (bctr < 1 || bctr > 3) {
- ioerr(IO, "Block check type must be between 1 and 3");
- bctr = 1;
- }
- break;
- case 'R': /* Retry limit */
- maxtry = atoi(p);
- break;
- case 'O': /* Timeout */
- rtimo = atoi(p);
- if (rtimo < 5) {
- ioerr(IO, "Timeout too short---using 5 second minimum");
- rtimo = 5;
- }
- break;
- case 'W': /* Window Slots */
- wslotr = atoi(p);
- if (wslotr < 1) wslotr = 1;
- break;
- case 'S': /* Default send overrides */
- switch (*p) {
- case 'P': /* Send packet size */
- spsiz = atoi(p+1);
- if (spsiz > 0) spsizf = 1;
- break;
- case 'O': /* Send timeout */
- timint = atoi(p+1);
- if (timint > 0) {
- timef = 1;
- if (timint < 5) timint = 5;
- }
- break;
- default:
- sprintf(errbuf, "Illegal XPR Kermit option: %s", p-1);
- ioerr(IO, errbuf);
- break;
- }
- break;
- default:
- sprintf(errbuf, "Illegal XPR Kermit option: %s", p-1);
- ioerr(IO, errbuf);
- break;
- }
- }
- return 1;
- }
-
- /**
- *
- * Cleanup. Because of the way we do re-entrancy, we can use the
- * Aztec malloc()/free(), which sets up the _cln pointer as shown
- * to clean up all allocated memory. Following this, we deallocate
- * the data segment in a re-entrant way as well.
- *
- **/
-
- void (*_cln)(void);
-
- long
- XProtocolCleanup(IO)
- struct XPR_IO *IO;
- {
- if (IO->xpr_data != NULL) {
- NewDataSeg(IO->xpr_data);
- if (_cln)
- (*_cln)();
- FreeMem(IO->xpr_data, &_H2_end - &_H1_org + 4);
- IO->xpr_data = NULL;
- }
-
- return (1L);
- }
-
- int
- XPRParity(IO)
- struct XPR_IO *IO;
- {
- long status;
-
- /* check out parity */
- if ((xsetserial = IO->xpr_setserial) != NULL) {
- status = calld(xsetserial, -1L);
- if (status & 0x00000001L)
- return 1;
- else
- return 0;
- } else
- return 0; /* Assume no parity if can't tell. */
- }
-
- void
- XPRLong(IO, i)
- struct XPR_IO *IO;
- long i;
- {
- struct XPR_UPDATE xpru;
- char locbuf[80];
-
- if ((xupdate = IO->xpr_update) == NULL)
- return;
- /* debug: show long value */
- xpru.xpru_updatemask = XPRU_MSG;
- sprintf(locbuf, "%lx", i);
- xpru.xpru_msg = &locbuf[0];
- (void) calla(xupdate, &xpru);
- }
-
- /*
- * Get all the callback routines we need. We do this because there is a
- * small chance that the callbacks could change dynamically.
- */
- int
- setup(IO)
- struct XPR_IO *IO;
- {
-
- if (InitData(IO) == 0)
- return 0;
- /*
- * These are the call-backs we need. If any of them isn't provided, quit.
- * Could do some error reporting if at least xupdate is there.
- */
- if ((xupdate = IO->xpr_update) == NULL)
- return 0;
- if ((xswrite = IO->xpr_swrite) == NULL)
- return 0;
- if ((xfopen = IO->xpr_fopen) == NULL)
- return 0;
- if ((xfclose = IO->xpr_fclose) == NULL)
- return 0;
- if ((xfread = IO->xpr_fread) == NULL)
- return 0;
- if ((xsread = IO->xpr_sread) == NULL)
- return 0;
- if ((xchkabort = IO->xpr_chkabort) == NULL)
- return 0;
- if ((xfnext = IO->xpr_fnext) == NULL)
- return 0;
- if ((xffirst = IO->xpr_ffirst) == NULL)
- return 0;
- if ((xsflush = IO->xpr_sflush) == NULL)
- return 0;
- if ((xfwrite = IO->xpr_fwrite) == NULL)
- return 0;
- if ((xgets = IO->xpr_gets) == NULL)
- return 0;
- if ((xsetserial = IO->xpr_setserial) == NULL)
- return 0;
- /*
- * Here are callbacks we can do without.
- */
- xchkmisc = IO->xpr_chkmisc;
- if (IO->xpr_extension >= 2)
- xunlink = IO->xpr_unlink;
- else
- xunlink = NULL;
- if (IO->xpr_extension >= 3)
- xsquery = IO->xpr_squery;
- else
- xsquery = NULL;
- xfinfo = IO->xpr_finfo;
-
- /*
- * Some Kermit setup stuff. Allocate buffers for send and receive.
- */
- if (getiobs() < 0)
- return 0;
- if (inibufs(SBSIZ,RBSIZ) < 0)
- return 0;
- /*
- * Set the speed and that we are in local mode.
- */
- local = 1;
- speed = ttgspd();
- return 1;
- }
-
- /*
- * Set the current context's data segment (small model) to the value
- * in DataSeg. Uses (undocumented) feature of compiler which allows
- * access to variables by name between #asm ... #endasm if preceded
- * by double percent sign.
- */
- /*lint -esym(528,NewDataSeg) */
-
- void
- NewDataSeg(void *DataSeg) {
- #ifndef _lint
-
- ;
- #asm
- movea.l %%DataSeg,a4
- add.l #32766,a4
- #endasm
-
- #endif
- }
-
- /*
- * Have the comm program display an error message for us, using a temporary
- * XPR_UPDATE structure; used to display errors before Vars gets allocated
- */
- void
- ioerr(IO, msg)
- struct XPR_IO *IO;
- char *msg;
- {
- struct XPR_UPDATE xpru;
-
- if ((xupdate = IO->xpr_update) != NULL) {
- xpru.xpru_updatemask = XPRU_ERRORMSG;
- xpru.xpru_errormsg = msg;
- (void) calla(xupdate, &xpru);
- }
- }
-
- /**
- *
- * The following functions setup the proper registers for the call-back
- * functions.
- *
- **/
-
- #ifndef _lint
-
- #asm
- public _callad
- _callad:
- movea.l 8(sp),a0 ; Second argument goes in a0
- move.l 12(sp),d0 ; Third argument goes in d0
- /*
- * Now this is a trick to avoid using another register.
- * Charlie taught me this...
- */
- move.l 4(sp),-(sp) ; First argument is function
- rts
-
- public _calladda
- _calladda:
- movea.l 8(sp),a0 ; Second argument goes in a0
- move.l 12(sp),d0 ; Third argument goes in d0
- move.l 16(sp),d1 ; Fourth argument goes in d1
- movea.l 20(sp),a1 ; Fifth argument goes in a1
- move.l 4(sp),-(sp) ; First argument is function
- rts
-
- public _calldaa
- _calldaa:
- move.l 8(sp),d0 ; Second argument goes in d0
- movea.l 12(sp),a0 ; Third argument goes in a0
- movea.l 16(sp),a1 ; Fourth argument goes in a1
- move.l 4(sp),-(sp) ; First argument is function
- rts
-
- public _calla
- _calla:
- movea.l 8(sp),a0 ; Second argument goes in a0
- move.l 4(sp),-(sp) ; First argument is function
- rts
-
- public _calld
- _calld:
- move.l 8(sp),d0 ; Second argument goes in d0
- move.l 4(sp),-(sp) ; First argument is function
- rts
-
- public _callaa
- _callaa:
- movea.l 8(sp),a0 ; Second argument goes in a0
- movea.l 12(sp),a1 ; Third argument goes in a1
- move.l 4(sp),-(sp) ; First argument is function
- rts
-
- public _callda
- _callda:
- move.l 8(sp),d0 ; Second argument goes in d0
- movea.l 12(sp),a0 ; Third argument goes in a0
- move.l 4(sp),-(sp) ; First argument is function
- rts
-
- public _calladd
- _calladd:
- movea.l 8(sp),a0 ; Second argument goes in a0
- move.l 12(sp),d0 ; Third argument goes in d0
- move.l 16(sp),d1 ; Fourth argument goes in d1
- move.l 4(sp),-(sp) ; First argument is function
- rts
-
- #endasm
- /*
- * Could have added any other functions needed for other call-backs.
- * Could have written a fancier single one... Could've...
- */
- #endif
-
- #ifdef DYNAMIC
- /* Allocate file i/o buffers */
-
- char *zinbuffer, *zoutbuffer;
-
- int
- getiobs() {
- if (!zinbuffer)
- zinbuffer = (char *)malloc(INBUFSIZE);
- if (!zinbuffer) return(-1);
- if (!zoutbuffer)
- zoutbuffer = (char *)malloc(OBUFSIZE);
- if (!zoutbuffer) return(-1);
- debug(F100,"getiobs ok","",0);
- return(0);
- }
-
- #endif /* DYNAMIC */
-